package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.IdAndNumDTO;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.tianji.learning.mapper.LearningLessonMapper;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-03-05
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {

    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final LearningRecordMapper recordMapper;

    @Override
    @Transactional
    public void addUserLessons(Long userId, List<Long> courseIds) {
        //1.查询课程有效期
        List<CourseSimpleInfoDTO> courseInfos = courseClient.getSimpleInfoList(courseIds);
        if (CollUtils.isEmpty(courseInfos)) {
            //课程不存在，无法添加
            log.error("课程不存在，无法添加课程：{}", courseIds);
            return;
        }
        //2.循环遍历，处理learningLesson数据
        List<LearningLesson> list = new ArrayList<>(courseInfos.size());
        for (CourseSimpleInfoDTO courseInfo : courseInfos) {
            LearningLesson lesson = new LearningLesson();
            //2.1获取过期时间
            Integer validDuration = courseInfo.getValidDuration();
            if (validDuration != null || validDuration > 0) {
                LocalDateTime now = LocalDateTime.now();
                lesson.setCreateTime(now);
                lesson.setExpireTime(now.plusMonths(validDuration));
            }
            //2.2添加userId和courseId
            lesson.setUserId(userId);
            lesson.setCourseId(courseInfo.getId());
            list.add(lesson);
        }
        //3.批量新增
        saveBatch(list);
    }

    @Override
    public PageDTO<LearningLessonVO> queryMyLessons(PageQuery pageQuery) {
        //1.获取当前用户登录
        //select *from learning_lesson where user_id = #{userId} order by latest_time limit #{pageSize} offset #{pageNum}
        Long userId = UserContext.getUser();
        //2.分页查询
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .page(pageQuery.toMpPage("latest_learn_time", false));
        List<LearningLesson> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        //3.查询课程信息
        Map<Long, CourseSimpleInfoDTO> cMap = queryCourseSimoleInfoList(records);

        //4.组装VO返回
        List<LearningLessonVO> list = new ArrayList<>(records.size());
        //4.1循环遍历，把learningLesson和courseSimpleInfo组装成LearningLessonVO
        for (LearningLesson record : records) {
            //4.2拷贝基础属性到Vo
            LearningLessonVO vo = BeanUtils.copyBean(record, LearningLessonVO.class);
            //4.3获取课程基本信息，填充到vo
            CourseSimpleInfoDTO info = cMap.get(record.getCourseId());
            vo.setCourseName(info.getName());
            vo.setCourseCoverUrl(info.getCoverUrl());
            vo.setCourseAmount(info.getSectionNum());
            list.add(vo);
        }
//        return new PageDTO<>(page.getTotal(),page.getPages(), list);
        return PageDTO.of(page, list);
    }

    private Map<Long, CourseSimpleInfoDTO> queryCourseSimoleInfoList(List<LearningLesson> records) {
        //3.1获取课程id
        Set<Long> cids = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());
        //3.2.查询课程信息
        List<CourseSimpleInfoDTO> courseInfos = courseClient.getSimpleInfoList(cids);
        if (CollUtils.isEmpty(courseInfos)) {
            //课程不存在，无法添加
            throw new BadRequestException("课程不存在，无法添加课程：{}");
        }
        //3.3把集合转换为map，key为课程id,value为课程信息
        Map<Long, CourseSimpleInfoDTO> cMap = courseInfos.stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, courseSimpleInfoDTO -> courseSimpleInfoDTO));
        return cMap;
    }

    @Override
    public LearningLessonVO queryLessonByCourserId(Long courseId) {
        //1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.查询课程表信息
        LearningLesson lesson = getOne(bulidUserIdAndCoureseIdWrapper(userId, courseId));
        if (lesson == null) {
            return null;
        }
        //3.封装处理Vo
        return BeanUtils.copyBean(lesson, LearningLessonVO.class);
    }

    @Override
    public LearningLessonVO queryNowLesson() {
        //1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.查询正在学习的课程表信息
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getStatus, LessonStatus.LEARNING)
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .last("limit 1")
                .one();
        if (lesson == null) {
            return null;
        }
        //3.拷贝PO基础属性到VO
        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        //4.查询课程信息
        CourseFullInfoDTO info = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (info == null) {
            throw new BadRequestException("课程不存在");
        }
        vo.setCourseName(info.getName());
        vo.setCourseCoverUrl(info.getCoverUrl());
        vo.setCourseAmount(info.getSectionNum());
        //5.统计课表中的课程数量
        Integer courseAmount = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .count();
        vo.setCourseAmount(courseAmount);
        //6.查询最近学习的小节信息
        List<CataSimpleInfoDTO> cataInfos = catalogueClient.batchQueryCatalogue(CollUtils.singletonList(lesson.getLatestSectionId()));
        if (CollUtils.isNotEmpty(cataInfos)) {
            CataSimpleInfoDTO cataInfo = cataInfos.get(0);
            vo.setLatestSectionName(cataInfo.getName());
            vo.setLatestSectionIndex(cataInfo.getCIndex());
        }
        return vo;
    }

    @Override
    public void deleteCourseFromLesson(Long userId, Long courseId) {
        //1.获取当前登录用户
        if (userId == null) {
            userId = UserContext.getUser();
        }
        //2.删除课程
        remove(bulidUserIdAndCoureseIdWrapper(userId, courseId));
    }

    @Override
    public Integer countLearningByCourse(Long courseId) {
        return lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .in(LearningLesson::getStatus,
                        LessonStatus.NOT_BEGIN.getValue(),
                        LessonStatus.LEARNING.getValue(),
                        LessonStatus.FINISHED.getValue())
                .count();

    }

    @Override
    public Long isLessonValid(Long courseId) {
        //1.获取当前登录用户
        Long userId = UserContext.getUser();
        if (userId == null){
            return null;
        }
        //2.查询课程表信息
        LearningLesson lesson = getOne(bulidUserIdAndCoureseIdWrapper(userId, courseId));
        if (lesson == null) {
            return null;
        }
        return lesson.getId();
    }

    @Override
    public LearningLesson queryByUserIdAndCourseId(Long userId, Long courseId) {
        return  getOne(bulidUserIdAndCoureseIdWrapper(userId, courseId));
    }

    @Override
    public void createLessoningPlans(Long courseId, Integer freq) {
        //1.获取当前用户
        Long userId = UserContext.getUser();
        //2.查询课表中的指定课程有关的的信息
        LearningLesson lesson = queryByUserIdAndCourseId(userId, courseId);
        AssertUtils.isNotNull(lesson, "课程信息不存在");
        //3.修改数据
        LearningLesson l = new LearningLesson();
        l.setId(lesson.getId());
        l.setWeekFreq(freq);
        if (lesson.getPlanStatus() == PlanStatus.NO_PLAN){
            l.setPlanStatus(PlanStatus.PLAN_RUNNING);
        }
        updateById(l);
    }

    @Override
    public LearningPlanPageVO queryMyPlans(PageQuery query) {
        LearningPlanPageVO result = new LearningPlanPageVO();
        //1.获取到当前用户
        Long userId = UserContext.getUser();
        //2.获取本周起始时间
        LocalDate now = LocalDate.now();
        LocalDateTime begin = DateUtils.getWeekBeginTime(now);
        LocalDateTime end = DateUtils.getWeekEndTime(now);
        //3查询总的统计数据
        //3.1.本周总的学习小结数量
        Integer weekFimsihed = recordMapper.selectCount(new LambdaQueryWrapper<LearningRecord>()
                .eq(LearningRecord::getUserId, userId)
                .eq(LearningRecord::getFinished, true)
                .gt(LearningRecord::getFinishTime, begin)
                .lt(LearningRecord::getFinishTime, end)
        );
        result.setWeekFinished(weekFimsihed);
        //3.2。本周总督计划学习小结数量
        Integer weekTotalPlan = getBaseMapper().queryPlanTotal(userId);
        result.setWeekTotalPlan(weekTotalPlan);
        //3.3.TODO 本周学习积分

        //4.查询分页数据
        //4.1.分页查询课表信息以及学习计划信息
        Page<LearningLesson> p = lambdaQuery()
                .eq(LearningLesson::getUserId,userId)
                .eq(LearningLesson::getPlanStatus,PlanStatus.PLAN_RUNNING)
                .in(LearningLesson::getStatus,LessonStatus.NOT_BEGIN,LessonStatus.LEARNING)
                .page(query.toMpPage("latest_learn_time", false));
        List<LearningLesson> records = p.getRecords();
        if (CollUtils.isEmpty(records)){
            return result.emptyPage(p);
        }
        //4.2.查询课表对印的课程信息
        Map<Long, CourseSimpleInfoDTO> cMap = queryCourseSimoleInfoList(records);
        //4.3.统计每一个课程本周已学习小姐数量
        List<IdAndNumDTO> list = recordMapper.countLearnedSections(userId, begin, end);
        Map<Long, Integer> countMap = IdAndNumDTO.toMap(list);
        //4.4.封装数据
        List<LearningPlanVO> volist = new ArrayList<>(records.size());
        for (LearningLesson r : records) {
            //4.4.1.拷贝PO基础属性到VO
            LearningPlanVO vo = BeanUtils.copyBean(r, LearningPlanVO.class);
            //4.4.2.填充课程详细信息
            CourseSimpleInfoDTO cInfo = cMap.get(r.getCourseId());
            if (cInfo != null){
                vo.setCourseName(cInfo.getName());
                vo.setSections(cInfo.getSectionNum());
            }
            //4.4.3每个课程本周已学习小结数量
            vo.setWeekLearnedSections(countMap.getOrDefault(r.getId(), 0));
            volist.add(vo);
        }
        return result.pageInfo(p.getTotal(),p.getPages(), volist);
    }

    private LambdaQueryWrapper<LearningLesson> bulidUserIdAndCoureseIdWrapper(Long userId, Long courseId) {
        LambdaQueryWrapper<LearningLesson> queryWrapper = new QueryWrapper<LearningLesson>()
                .lambda()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId);
        return queryWrapper;
    }
}
